package com.enjoy.concurrent.ch6;

import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

@Slf4j
public class ForkJoinTest {


    private class SumTask extends RecursiveTask<Long> {

        public static final int THRESHOLD = 1000000;

        private int low;
        private int high;
        private int[] array;

        public SumTask(int low, int high, int[] array) {
            this.low = low;
            this.high = high;
            this.array = array;
        }

        @Override
        protected Long compute() {
            //当任务拆到小于阈值时开始求和
            if (high - low <= THRESHOLD) {
                long sum = 0;
                for (int i = low; i < high; ++i) {
                    sum += array[i];
                }
                return sum;
            } else {
                int mid = low + (high - low) / 2;
                SumTask left = new SumTask(low, mid, array);
                SumTask right = new SumTask(mid, high, array);
                //提交任务
                left.fork();
                right.fork();

                //获取任务的结果
                Long leftSum = left.join();
                Long rightSum = right.join();
                return leftSum + rightSum;
            }
        }
    }

    private int[] buildArray(int length) {
        int[] array = new int[length];
        Random random = new Random();
        for (int i = 0; i < length; i++) {
            array[i] = random.nextInt(100000);
            if (array[i] < 0) {
                log.info(array[i] + "");
            }
        }
        return array;
    }

    @Test
    public void test1() throws ExecutionException, InterruptedException {
        int[] array = buildArray(100000000);

        long start = System.currentTimeMillis();
        long sum = 0;
        for (int value : array) {
            sum = sum + value;
        }
        long end = System.currentTimeMillis();

        log.info("结果:{}", sum);
        log.info("花费:{}ms", (end - start));


        ForkJoinPool forkJoinPool = new ForkJoinPool(Runtime.getRuntime().availableProcessors());
        long currentTimeMillis = System.currentTimeMillis();
        ForkJoinTask<Long> submit = forkJoinPool.submit(new SumTask(0, array.length, array));
        log.info("结果:{}", submit.get());
        log.info("花费:{}ms", System.currentTimeMillis() - currentTimeMillis);

        Thread.sleep(Integer.MAX_VALUE);
    }


    @Test
    public void test3() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i);
        }
    }

    @Test
    public void test4() {
        for (int i = 0; i < 10; ++i) {
            System.out.println(i);
        }
    }

}
